type Toptions_Picon$icon = keyof typeof Picon.mappings;
type Toptions_Picon$type = typeof Picon.types[number];
type Toptions_Picon$size = number | string;

type Toptions_Picon = {
    icon?: Toptions_Picon$icon;
    type?: Toptions_Picon$type;
    size?: Toptions_Picon$size;
};

class Picon extends _CP_<Toptions_Picon> {
    // ====================================================== 当前控件特殊实现 ====================================================== //
    static mappings = {
        'ok': { fa: 'check' },
        'reset': { fa: 'undo' },
        'clear': { fa: 'times' },
    };

    static types = ['image', 'fa', 'fontawesome'] as const;

    static iconURL = function (icon: Toptions_Picon$icon) {
        return `url("/icons/${icon}.png")`;
    };

    // ====================================================== 初始化参数 ====================================================== //
    static defaultOptions: Toptions_Picon = {
    };
    protected override options_default(): Toptions_Picon {
        return Picon.defaultOptions;
    }
    protected override options_handlers(): Toptions_handlers<Toptions_Picon> {
        return {
            icon: {
                [Etype.string]: U.F.fn.obj,
            },
            type: {
                [Etype.string]: U.F.fn.obj,
            },
            size: {
                [Etype.string]: (value: string) => {
                    const size = U.S.toSize(value);
                    if (size) { return size; }
                    return DEFAULT;
                },
                [Etype.number]: (value: number) => {
                    if (U.N.isValue(value, Epzn.positive)) { return `${value}px`; }
                    return DEFAULT;
                },
            },
        };
    };
    protected override overloading_mapping(mapping: Toption_key_to_types_mapping<Toptions_Picon>): Toverloading_mapping<Toptions_Picon> {
        return [
            [
                { key: 'icon', types: mapping.get('icon')! },
            ],
            [
                { key: 'icon', types: mapping.get('icon')! },
                { key: 'type', types: mapping.get('type')! },
            ],
            [
                { key: 'icon', types: mapping.get('icon')! },
                { key: 'type', types: mapping.get('type')! },
                { key: 'size', types: mapping.get('size')! },
            ],
        ];
    }
    protected override options_checker(options: Toptions_Picon): void {
        if (!U.O.getProperty(Picon.mappings, options.icon!)) { delete options.icon; }
        if (Picon.types.indexOf(options.type!) < 0) { delete options.type; }
    }

    // ====================================================== 创建实例对象 ====================================================== //
    protected override topTag(): string { return 'span'; };
    protected override initializer(): void {
        if (Object.prototype.hasOwnProperty.call(this.options, 'icon')) {
            this.ele.addClass(this.options.icon as string);
            switch (this.options.type) {
                case 'fa':
                case 'fontawesome': {
                    _loadFA_();// 延迟加载FA
                    this.ele.addClass('fa')
                        .addClass('fa-' + Picon.mappings[this.options.icon as Toptions_Picon$icon].fa);
                } break;
                case 'image':
                default: {
                    this.ele.addClass('image')
                        .setStyle('backgroundImage', Picon.iconURL(this.options.icon as Toptions_Picon$icon));
                } break;
            }
        }

        if (Object.prototype.hasOwnProperty.call(this.options, 'size')) {
            this.ele
                .setStyle('width', this.options.size)
                .setStyle('height', this.options.size);
            if ((this.options.size as string).endsWith('%')) {// 百分比大小图标，加入观察任务，直到渲染后才能计算数值。
                _icon_resize_observer_.observe(this.ele.ele()!);
            } else {
                if (this.ele.hasClass('image')) {
                    this.ele.setStyle('backgroundSize', this.options.size);
                } else if (this.ele.hasClass('fa')) {
                    this.ele
                        .setStyle('lineHeight', this.options.size)
                        .setStyle('fontSize', this.options.size);
                }
            }
        }
    }
    protected override afterInitializer(): void {
    }
}

interface _IK_ {
    // ========= 创建实例对象（通用） ========= //
    /**
     * 创建控件
     * @returns 控件实例对象
     */
    icon(): KHTMLElement;

    /**
     * 创建控件
     * @param options 控件参数
     * @returns 控件实例对象
     */
    icon(options: Toptions_Picon): KHTMLElement;

    // ========= 创建实例对象（特殊） ========= //
    /**
     * 创建控件
     * @param icon 图标值
     * @param type 图标类型
     * @param size 图标大小
     * @returns 控件实例对象
     */
    icon(icon: Toptions_Picon$icon, type?: Toptions_Picon$type, size?: Toptions_Picon$size): KHTMLElement;
}
{
    K.icon = (...args: Array<any>) => { return new Picon(...args).ele; };
}

// 图标百分比大小处理器
const _icon_resize_observer_ = new ResizeObserver(entries => {
    for (let entry of entries) {
        const ele = entry.target as HTMLElement;
        const size = entry.contentRect.height;
        if (size) {
            // 有数据时，计算固定大小，立即关闭观察者，设置固定值。
            _icon_resize_observer_.unobserve(ele);
            const eleK = new KHTMLElement(ele);
            eleK
                .setStyle('width', `${size}px`)
                .setStyle('height', `${size}px`);
            if (eleK.hasClass('image')) {
                eleK.setStyle('backgroundSize', `${size}px`);
            } else if (eleK.hasClass('fa')) {
                eleK
                    .setStyle('lineHeight', `${size}px`)
                    .setStyle('fontSize', `${size}px`);
            }
        }
    }
});

// 延迟加载FA
let _loadFA_ = () => {
    _loadFA_ = U.F.fn.void;// 只加载一次
    const link = document.createElement('link');
    link.rel = 'stylesheet';
    link.href = '/fontawesome/css/all.min.css';
    document.head.appendChild(link);
};
